package com.me.myFramework.aop22.aop120;

import com.me.myFramework.aop22.aop120.intercept.method.AfterReturningAdviceInterceptor120;
import com.me.myFramework.aop22.aop120.intercept.method.MethodBeforeAdviceInterceptor120;
import com.me.myFramework.aop22.aop120.intercept.method.MethodInterceptor120;
import com.me.myFramework.aop22.aop120.intercept.method.MethodInvocation120;
import com.me.myFramework.aop22.aop120.intercept.method.ReflectiveMethodInvocation120;
import org.aopalliance.aop.Advice;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 《AOP-120》：  <br><br>
 * 
 * TODO 把 getProxy()方法 提取成工厂类，专门负责创建代理类。
 *  提取 getInterceptor方法，根据 Advice 创建 MethodInterceptor
 */
public class ProxyFactory120 {

    private Object target;
    private Advice advice;

    public ProxyFactory120(Object target, Advice advice) {
        this.target = target;
        this.advice = advice;
    }

    public Object getProxy() {
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                MethodInterceptor120 interceptor = getInterceptor();
                if (interceptor != null) {
                    MethodInvocation120 mi = new ReflectiveMethodInvocation120(proxy, target, method, args);
                    return interceptor.invoke(mi);
                }

                return method.invoke(target, args);
            }
        });
    }

    private MethodInterceptor120 getInterceptor() {
        if (this.advice == null) {
            return null;
        }

        if (advice instanceof MethodBeforeAdvice) {
            return new MethodBeforeAdviceInterceptor120((MethodBeforeAdvice) advice);
        } else if (advice instanceof AfterReturningAdvice) {
            return new AfterReturningAdviceInterceptor120((AfterReturningAdvice) advice);
        } else {
            throw new RuntimeException("GG, 未知的 Advice");
        }
    }

    private boolean isCustomMethod(String methodName) {
        return !("toString".equals(methodName) || "hashCode".equals(methodName) || "equals".equals(methodName)
                || "clone".equals(methodName));
    }

}
